// 三种状态
const WAITFOR = "waitFor"   //等待
const SUCCESS = "success"   //成功
const FAIL = "fail"         //拒绝

class MyPromise {
    constructor(executor) {
        try {
            executor(this.success, this.fail)
        } catch (e) {
            this.fail(e)
        }
    }
    state = WAITFOR; // 一开始是等待状态 
    res = undefined; //成功返回值
    err = undefined; // 错误信息

    //成功时回调,promise 多次调用,-->数组
    resAsyBack = [];
    // 失败时回调,promise 多次调用,-->数组
    errAsyBack = []; // 失败


    // 成功时
    success = (value) => {
        // 判断是否为 等待状态
        if (this.state !== WAITFOR) return
        // 状态为成功
        this.state = SUCCESS;
        // 返回成功值
        this.res = value
        // 异步 调用成功时状态 带参数或者不带参数 
        // this.resAsyBack && this.resAsyBack(this.res)

        // promise 多次调用,while循环 resAsyBack[],
        // 判断resAsyBack[].length长度不为0,shift返回第一个值并给它
        while(this.resAsyBack.length) this.resAsyBack.shift()()
        
    }
    // 失败时
    fail = (fai) => {
        // 判断是否为 等待状态
        if (this.state !== WAITFOR) return
        // 状态为 失败
        this.state = FAIL;
        // 返回失败值
        this.err = fai
        // 异步 调用成功时状态 带参数或者不带参数
        // this.errAsyBack && this.errAsyBack(this.err)

         // promise 多次调用,while循环 errAsyBack[],
        // 判断errAsyBack[].length长度不为0,shift返回第一个值并给它
        while(this.errAsyBack.length) this.errAsyBack.shift()()
        

    }
    // .then 属性
    then(resBack, errBack) {
        // 查看then 的参数是否存在
        resBack = resBack ? resBack : value=>value;
        errBack = errBack ? errBack : e=> { throw e}
        let promise2 = new MyPromise((resolve,resject)=>{
            // 先判断状态
            if (this.state === SUCCESS) {
                setTimeout(() => {
                    try {
                        // ^-- 成功时状态  x是then 返回值
                        let x = resBack(this.res)
                        // 成功回调,
                        //  resolve(x)
                        resolvePromise(promise2,x,resolve,resject)   
                    } catch (e) {
                        resject(e);
                    }
                }, 0);
            } else if (this.state === FAIL) {
                // ^-- 失败时状态 
                // errBack(this.err)
                setTimeout(() => {
                    try {
                        // ^-- 失败时状态  x是then 返回值
                        let x = errBack(this.err)
                        // 成功回调,
                        //  resolve(x)
                        resolvePromise(promise2,x,resolve,resject)   
                    } catch (e) {
                        resject(e);
                    }
                }, 0);
            } else {
                // 等待状态
                // console.log(this.state);
                // 将成功回调 存储起来
                // this.resAsyBack = resBack;
                // this.resAsyBack.push(resBack)
                this.resAsyBack.push(()=>{
                    setTimeout(() => {
                        try {
                            // ^-- 成功时状态  x是then 返回值
                            let x = resBack(this.res)
                            // 成功回调,
                            //  resolve(x)
                            resolvePromise(promise2,x,resolve,resject)   
                        } catch (e) {
                            resject(e);
                        }
                    }, 0);
                })
                //将失败回调 存储起来
                // this.errAsyBack = errBack;
                // this.errAsyBack.push(errBack)
                this.errAsyBack.push(()=>{
                    setTimeout(() => {
                        try {
                            // ^-- 失败时状态  x是then 返回值
                            let x = errBack(this.err)
                            // 成功回调,
                            //  resolve(x)
                            resolvePromise(promise2,x,resolve,resject)   
                        } catch (e) {
                            resject(e);
                        }
                    }, 0);
                })
            }
        });
        
        return promise2;
    }


    static all(array){
        let result = [];
        let index = 0;

        return new MyPromise((res,err)=>{
            function addData(key,value){
                result[key] = value;
                index++;
                if(index === array.length){
                    
                    res(result);
                }
            }
            for (let i=0;i<array.length;i++){
                let current = array[i]
                if(current instanceof MyPromise){
                    current.then(v=>addData(i,v),e=>err(e))
                }else{
                    addData(i,array[i])
                }
            }
            // res(result);
        })
    }

    static resolve(value){
        if(value instanceof MyPromise) return value
        return new MyPromise(res=> res(value))
    }

    finally(callback){
        return this.then(res=>{
            return MyPromise.resolve(callback()).then(()=>res)
            // callback()
            // return res
        },
        err=>{
            return MyPromise.resolve(callback()).then(()=>{ throw err })
            // callback();
            // throw err
        })
    }

    catch(failCallBack){
       return this.then(undefined,failCallBack)
    }

}

function resolvePromise(promise2,x,resolve,resject){
    
    if(x===promise2){
      return  resject(new TypeError("TypeError"))
    }
    if(x instanceof MyPromise){
        // x.then((v)=>{resolve(v)},(e)=>{resject(e)})
        x.then(resolve,resject)

    }else{
        resolve(x)
    }
}

// 导出，
module.exports = MyPromise